﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ESRI.ArcGIS.ArcCatalogUI;
using ESRI.ArcGIS.ArcMap;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.CartoUI;
using ESRI.ArcGIS.ArcMapUI;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.Desktop;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.GeoDatabaseUI;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.SystemUI;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.LocationUI;
using ESRI.ArcGIS.DataSourcesOleDB;
using System.IO;
using ConnectWithR.precipitation;
using ESRI.ArcGIS.Geoprocessor;
using ESRI.ArcGIS.DataManagementTools;
using ESRI.ArcGIS.AnalysisTools;
using RDotNet;
using ESRI.ArcGIS.DataSourcesRaster;
using System.Collections;
namespace ConnectWithR

{
    /// <summary>
    /// Main work flow class!
    /// </summary>
    public partial class Topmodel : Form
    {
        IMxDocument pMxDoc = (IMxDocument)ArcMap.Application.Document;
        IMap pMap = null;
        IFeatureLayer focusedLayer = null;
        IFields fields = null;
        IFeature feature = null;
        IField field = null;
        IFeatureLayer stationsLayer = null;
        IFeature selectedFeatureForSelection = null;
        IFeatureLayer selectedStationsLayer = null;
        IRasterLayer rasterLayer = null;
        ITable pTable = null;
        String dataType = "precipitation";
        String preFix = "GHCN:";
        double expandIndex1 = 0.6;
        double expandIndex2 = 0.6;
        DateTime startDate;
        DateTime endDate;
        IStandaloneTableCollection pStandAloneCollection = null;
        IStandaloneTable pStandaloneTable = null;
        IRasterLayer clippedRasterLayer = null;
        REngine engine = null;
        String DEMPath;
        Double[] ET0Values = { };
        Double[] PrecipitationValues = { };
        Double[] DischargeValues = { };
        Double drainageArea = 0.0;
        String dllPath = "";
        int series = 0;

        
        public Topmodel()
        {
            pMap = pMxDoc.FocusMap;
            this.pStandAloneCollection = (IStandaloneTableCollection)pMap;
            InitializeComponent();
        }

        private void Form2_Load(object sender, EventArgs e)
        {
            if (pMap.LayerCount == 0)
            {
                return;
            }
            
            //Show the layer names
            for (int i = 0; i < pMap.LayerCount; i++)
            {
                cboLayer.Items.Add(pMap.get_Layer(i).Name);
            }
            for (int i = 0; i < this.pStandAloneCollection.StandaloneTableCount; i++)
            {
                cboLayer.Items.Add(this.pStandAloneCollection.StandaloneTable[i].Name);
            }
            cboLayer.Text = pMap.get_Layer(0).Name;
            if (pMap.get_Layer(0) is IFeatureLayer)
            {
                this.focusedLayer = (IFeatureLayer)pMap.get_Layer(0);
                lblLayerName.Text = this.focusedLayer.Name;
            }
            if (pMap.get_Layer(0) is IRasterLayer)
            {
                this.rasterLayer = (IRasterLayer)pMap.get_Layer(0);
                lblLayerName.Text = this.rasterLayer.Name;
            }
            for (int i = 0; i < this.pMap.LayerCount; i++)
            {
                if (pMap.get_Layer(i) is IRasterLayer)
                {
                    cboDEM.Items.Add(this.pMap.get_Layer(i).Name);
                }
            }
            cboDEM.SelectedIndex = 0;
        }

        private void cboLayer_SelectedIndexChanged(object sender, EventArgs e)
        {
            cboFileds.Items.Clear();
            IFeatureLayer myLayer;
            
            for (int i = 0; i < pMap.LayerCount; i++)
            {
                if (cboLayer.Text == pMap.get_Layer(i).Name)
                {
                    if (pMap.get_Layer(i) is IFeatureLayer)
                    {
                        myLayer = (IFeatureLayer)pMap.get_Layer(i);
                        this.focusedLayer = myLayer;
                        lblLayerName.Text = this.focusedLayer.Name;
                        this.fields = this.focusedLayer.FeatureClass.Fields;
                        for (int j = 0; j < this.fields.FieldCount; j++)
                        {
                            cboFileds.Items.Add(this.fields.get_Field(j).Name);
                        }
                        cboFileds.Text = this.fields.get_Field(0).Name;
                        return;
                    }
                    if (pMap.get_Layer(i) is IRasterLayer)
                    {
                        this.rasterLayer = (IRasterLayer)pMap.get_Layer(i);
                        lblLayerName.Text = this.rasterLayer.Name;
                        cboFileds.Items.Clear();
                        cboFileds.Text = "";
                        lblFieldName.Text = "";
                    }
                }
            }

            for (int i = 0; i < pStandAloneCollection.StandaloneTableCount; i++)
            {
                if (pStandAloneCollection.StandaloneTable[i].Name == cboLayer.Text)
                {
                    this.pStandaloneTable = pStandAloneCollection.StandaloneTable[i];
                    lblLayerName.Text = this.pStandaloneTable.Name;
                    this.fields = this.pStandaloneTable.Table.Fields;
                    for (int j = 0; j < this.fields.FieldCount; j++)
                    {
                        cboFileds.Items.Add(this.fields.get_Field(j).Name);
                    }
                    cboFileds.Text = this.fields.get_Field(0).Name;
                    return;
                }
            }
        }

        private void cboFileds_SelectedIndexChanged(object sender, EventArgs e)
        {
            IField myField = null;
            for (int i = 0; i < this.fields.FieldCount; i++)
            {
                if (cboFileds.Text == this.fields.get_Field(i).Name)
                {
                    myField = this.fields.get_Field(i);
                    this.field = myField;
                    lblFieldName.Text = myField.Name;
                }
            }
            //IFeatureCursor featureCursorGet = this.focusedLayer.Search(null, false);
            //IFeature myFeature = featureCursorGet.NextFeature();
            //String firValue = Convert.ToString(myFeature.get_Value(myFeature.Fields.FindField(myField.Name)));
            //this.feature = myFeature;
            //int index;
            //String value;
            //while (myFeature != null)
            //{
            //    index = myFeature.Fields.FindField(myField.Name);
            //    value = Convert.ToString(myFeature.get_Value(index));
            //    myFeature = featureCursorGet.NextFeature();
            //}
        }

        

        private void cboLayer_MouseClick(object sender, MouseEventArgs e)
        {
            this.pMap = pMxDoc.FocusMap;
            this.pStandAloneCollection = (IStandaloneTableCollection)this.pMap;
            cboLayer.Items.Clear();
            for (int i = 0; i < pMap.LayerCount; i++)
            {
                cboLayer.Items.Add(pMap.get_Layer(i).Name);
            }
            for (int i = 0; i < this.pStandAloneCollection.StandaloneTableCount; i++)
            {
                cboLayer.Items.Add(this.pStandAloneCollection.StandaloneTable[i].Name);
            }
        }

        private void btnSearchStation_Click(object sender, EventArgs e)
        {
            double num;
            Boolean isPrecipitation = false;
            if (rdoPrecipitation.Checked)
            {
                this.preFix = "GHCN:";
                this.dataType = "Precipitation";
                isPrecipitation = true;
            }
            if (rdoDischarge.Checked)
            {
                this.preFix = "NWISDV:";
                this.dataType = "Discharge";
            }
            if (rdoET0.Checked)
            {
                this.preFix = "NLDAS_NOAH:";
                this.dataType = "ET0";
            }
            if(!double.TryParse(txtExpandIndex1.Text.Trim(),out num) || !double.TryParse(txtExpandIndex2.Text.Trim(),out num))
            {
                txtExpandIndex1.Text = "0.6";
                txtExpandIndex2.Text = "0.6";
                MessageBox.Show("Expand Index should be a number!");
                return;
            }

            this.expandIndex1 = Convert.ToDouble(txtExpandIndex1.Text);
            this.expandIndex2 = Convert.ToDouble(txtExpandIndex2.Text);
            this.selectedFeatureForSelection = DataUtility.selectFeatureForSelection(this.focusedLayer);
            if (this.selectedFeatureForSelection == null)
            {
                MessageBox.Show("no feature is selected.");
                return;
            }

            this.pTable = DataUtility.createStationTable(this.dataType);
            if (this.pTable == null)
            {
                MessageBox.Show("no table is created.");
                return;
            }

            if (pTable.RowCount(null) <= 0 && rdoPrecipitation.Checked)
            {
                //Utility.insertSiteInfo(this.pTable, this.preFix, proxy.getPrecipitationClient());
                SiteInfoInsertor preSiteInfoInsertor = new PrecipitationManager(proxy.getPrecipitationClient());
                preSiteInfoInsertor.insertSiteInfo(this.pTable, this.preFix );
            }

            if (pTable.RowCount(null) <= 0 && rdoDischarge.Checked)
            {
                //Utility.insertSiteInfo(this.pTable, this.preFix, proxy.getDischargeClient());
                SiteInfoInsertor dischargeInfoInsertor = new DischargeManager(proxy.getDischargeClient());
                dischargeInfoInsertor.insertSiteInfo(this.pTable, this.preFix);
            }

            if (pTable.RowCount(null) <= 0 && rdoET0.Checked)
            {
                //Utility.insertSiteInfo(this.pTable, this.preFix, proxy.getDischargeClient());
                SiteInfoInsertor ET0InfoInsertor = new EvapotranspirationManager(proxy.getEvapotranspirationClient());
                ET0InfoInsertor.insertSiteInfo(this.pTable, this.preFix);
            }

            this.stationsLayer = DataUtility.createStationsLayer(this.pTable, this.dataType);
            if (this.stationsLayer == null)
            {
                MessageBox.Show("no station layer has been created");
            }

            DataUtility.exportLayer(this.stationsLayer);

            this.stationsLayer = DataUtility.addShapeFile(this.stationsLayer.Name);

            this.selectedStationsLayer = DataUtility.selectStations(this.stationsLayer, this.selectedFeatureForSelection, this.dataType, this.expandIndex1, this.expandIndex2, isPrecipitation, out this.drainageArea);

            if (this.selectedStationsLayer != null)
            {
                pMap.AddLayer(this.selectedStationsLayer);
                pMxDoc.ActiveView.Refresh();
            }

        }

        //The codes listed below ensure only numbers can be entered
        private void txtExpandIndex1_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (DataUtility.isNumber(e))
            {
                e.Handled = false;
            }
            else
            {
                MessageBox.Show("only numbers can be entered");
                e.Handled = true;
            }
        }

        private void txtExpandIndex2_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (DataUtility.isNumber(e))
            {
                e.Handled = false;
            }
            else
            {
                MessageBox.Show("only numbers can be entered");
                e.Handled = true;
            }
        }

        private void btnDownload_Click(object sender, EventArgs e)
        {
            if (dtpStart.Value.CompareTo(dtpEnd.Value) >= 0)
            {
                MessageBox.Show("Start date can no be later than end date!");
                return;
            }

            this.startDate = dtpStart.Value;
            this.endDate = dtpEnd.Value;

            String tableLayerName = "";
            this.pTable = DataUtility.createTimeSeriesTable(this.dataType, out tableLayerName);

            if (rdoPrecipitation.Checked)
            {
                this.preFix = "GHCN:";
                this.dataType = "Precipitation";
                Downloador preManager = new PrecipitationManager(proxy.getPrecipitationClient());
                this.pTable = preManager.downloadData(this.focusedLayer, this.pTable, this.startDate, this.endDate, this.field);
            }
            if (rdoDischarge.Checked)
            {
                this.preFix = "NWISDV:";
                this.dataType = "Discharge";
                Downloador dischargeManager = new DischargeManager(proxy.getDischargeClient());
                this.pTable = dischargeManager.downloadData(this.focusedLayer, this.pTable, this.startDate, this.endDate, this.field);
            }
            if (rdoET0.Checked)
            {
                this.preFix = "NLDAS_NOAH:";
                this.dataType = "ET0";
                Downloador ET0Manager = new EvapotranspirationManager(proxy.getEvapotranspirationClient());
                this.pTable = ET0Manager.downloadData(this.focusedLayer, this.pTable, this.startDate, this.endDate, this.field);
            }

            //this.pTable = Utility.downloadData(this.focusedLayer, proxy.getPrecipitationClient(), this.pTable, this.startDate, this.endDate, this.field);
            DataUtility.addTable(this.pMap, this.pTable, tableLayerName);
            pMxDoc.UpdateContents();
        }

        private void cboDEM_SelectedIndexChanged(object sender, EventArgs e)
        {
            for (int i = 0; i < this.pMap.LayerCount; i++)
            {
                if(this.pMap.get_Layer(i).Name == cboDEM.Text)
                {
                    this.rasterLayer = (IRasterLayer)pMap.get_Layer(i);
                    lblRasterName.Text = this.rasterLayer.Name;
                }
            }

        }

        private void btnClip_Click(object sender, EventArgs e)
        {
            this.clippedRasterLayer = DataUtility.clipDEM(this.focusedLayer, this.rasterLayer, out this.drainageArea);
            if (this.clippedRasterLayer == null) 
            {
                MessageBox.Show("No raster has been clipped!");
                return;
            }
            this.pMap.AddLayer((ILayer)this.clippedRasterLayer);
            pMxDoc.ActivatedView.Refresh();

        }

        private void cboDEM_MouseClick(object sender, MouseEventArgs e)
        {
            this.pMap = pMxDoc.FocusMap;
            cboDEM.Items.Clear();
            for (int i = 0; i < this.pMap.LayerCount; i++)
            {
                if (pMap.get_Layer(i) is IRasterLayer)
                {
                    cboDEM.Items.Add(this.pMap.get_Layer(i).Name);
                }
            }
        }

        private void btnRdll_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog folderDlg = new FolderBrowserDialog();
            folderDlg.ShowDialog();
            this.dllPath = folderDlg.SelectedPath;
            lblPath.Text = this.dllPath;
            RUtility.initialR(this.dllPath);
        }

        private void rdoMonte_CheckedChanged(object sender, EventArgs e)
        {
            txtTimes.Visible = true;
            lblTimes.Visible = true;
            rdoRDischarge.Visible = false;
            rdoNash.Checked = true;
        }

        private void rdoCustom_CheckedChanged(object sender, EventArgs e)
        {
            txtTimes.Visible = false;
            lblTimes.Visible = false;
            rdoRDischarge.Visible = true;
            rdoDischarge.Checked = true ;
        }

        private void rdoNash_CheckedChanged(object sender, EventArgs e)
        {
            btnDischarge.Visible = true;
            lblDischarge.Visible = true;
        }

        private void rdoRDischarge_CheckedChanged(object sender, EventArgs e)
        {
            btnDischarge.Visible = false;
            lblDischarge.Visible = false;
        }


        private void txtQs0_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (DataUtility.isNumber(e))
            {
                e.Handled = false;
            }
            else
            {
                MessageBox.Show("only numbers can be entered");
                e.Handled = true;
            }
        }

        private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (DataUtility.isNumber(e))
            {
                e.Handled = false;
            }
            else
            {
                MessageBox.Show("only numbers can be entered");
                e.Handled = true;
            }
        }

        private void textBox2_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (DataUtility.isNumber(e))
            {
                e.Handled = false;
            }
            else
            {
                MessageBox.Show("only numbers can be entered");
                e.Handled = true;
            }
        }

        private void textBox3_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (DataUtility.isNumber(e))
            {
                e.Handled = false;
            }
            else
            {
                MessageBox.Show("only numbers can be entered");
                e.Handled = true;
            }
        }

        private void textBox4_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (DataUtility.isNumber(e))
            {
                e.Handled = false;
            }
            else
            {
                MessageBox.Show("only numbers can be entered");
                e.Handled = true;
            }
        }

        private void textBox9_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (DataUtility.isNumber(e))
            {
                e.Handled = false;
            }
            else
            {
                MessageBox.Show("only numbers can be entered");
                e.Handled = true;
            }
        }

        private void textBox8_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (DataUtility.isNumber(e))
            {
                e.Handled = false;
            }
            else
            {
                MessageBox.Show("only numbers can be entered");
                e.Handled = true;
            }
        }

        private void textBox7_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (DataUtility.isNumber(e))
            {
                e.Handled = false;
            }
            else
            {
                MessageBox.Show("only numbers can be entered");
                e.Handled = true;
            }
        }

        private void textBox6_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (DataUtility.isNumber(e))
            {
                e.Handled = false;
            }
            else
            {
                MessageBox.Show("only numbers can be entered");
                e.Handled = true;
            }
        }

        private void txtTimes_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (DataUtility.isNumber(e))
            {
                e.Handled = false;
            }
            else
            {
                MessageBox.Show("only numbers can be entered");
                e.Handled = true;
            }
        }

        private void btnDEM_Click(object sender, EventArgs e)
        {
            String layerName = cboLayer.Text;
            ILayer layer = null;
            layer = DataUtility.getCBOLayer(this.pMap, layerName);
            if (layer is IRasterLayer)
            {
                this.DEMPath = DataUtility.getDEMPath(layer);
                lblDEM.Text = layer.Name;
            }
            else
            {
                MessageBox.Show("Please choose a DEM Layer!");
                return;
            }
        }

        private void btnET0_Click(object sender, EventArgs e)
        {
            String tableName = cboLayer.Text;
            IMap pMap = pMxDoc.FocusMap;
            IStandaloneTable pAloneTable = DataUtility.getCBOTable(pMap, tableName);
            if (pAloneTable == null)
            {
                MessageBox.Show("Please select the table which contains the evapotranspiration data!");
                return;
            }
            ITable pTable = pAloneTable.Table;
            String variableCode = pTable.GetRow(1).get_Value(pTable.FindField("TSTypeID"));
            if (variableCode == "NLDAS:NLDAS_NOAH0125_H.002:EVPsfc")
            {
                this.ET0Values = RUtility.getValues(pTable);
                lblET0.Text = pAloneTable.Name;
            }
            else
            {
                MessageBox.Show("Please select the evapotranspiration table");
                return;
            }

        }

        private void btnRain_Click(object sender, EventArgs e)
        {
            String tableName = cboLayer.Text;
            IMap pMap = pMxDoc.FocusMap;
            IStandaloneTable pAloneTable = DataUtility.getCBOTable(pMap, tableName);
            if (pAloneTable == null)
            {
                MessageBox.Show("Please select the table which contains the precipitation data!");
                return;
            }
            ITable pTable = pAloneTable.Table;
            String variableCode = pTable.GetRow(1).get_Value(pTable.FindField("TSTypeID"));
            if (variableCode == "GHCN:8")
            {
                this.PrecipitationValues = RUtility.getValues(pTable);
                lblRain.Text = pAloneTable.Name;
            }
            else
            {
                MessageBox.Show("Please select the evapotranspiration table");
                return;
            }
        }

        private void btnDischarge_Click(object sender, EventArgs e)
        {
            String tableName = cboLayer.Text;
            IMap pMap = pMxDoc.FocusMap;
            IStandaloneTable pAloneTable = DataUtility.getCBOTable(pMap, tableName);
            if (pAloneTable == null)
            {
                MessageBox.Show("Please select the table which contains the discharge data!");
                return;
            }
            ITable pTable = pAloneTable.Table;
            String variableCode = pTable.GetRow(1).get_Value(pTable.FindField("TSTypeID"));
            if (variableCode == "NWIDV:00060")
            {
                this.DischargeValues = RUtility.getValues(pTable);
                lblDischarge.Text = pAloneTable.Name;
            }
            else
            {
                MessageBox.Show("Please select the discharge table");
                return;
            }
        }

        private void btnCalculate_Click(object sender, EventArgs e)
        {
            ITable pTable = null;


            if (rdoCustom.Checked && rdoRDischarge.Checked)
            {

                MessageBox.Show("custom && discharge");

                //List<Double> test = new List<Double>();
                //test.Add(0.00004);
                //test.Add(1);
                //test.Add(0.2);
                //test.Add(0.02);
                //test.Add(2);
                //test.Add(3);
                //test.Add(1000);
                //test.Add(2500);
                //test.Add(0.01);
                //test.Add(5);
                //test.Add(1);


                List<Double> parameters = new List<double>();
                Double booleanTemp = 0;
                if (Double.TryParse(txtQs0.Text, out booleanTemp))
                {
                    parameters.Add(Convert.ToDouble(txtQs0.Text));
                }
                else
                {
                    MessageBox.Show("parameter Qs0 should be a number!");
                    return;
                }

                if (Double.TryParse(txtlnTe.Text, out booleanTemp))
                {
                    parameters.Add(Convert.ToDouble(txtlnTe.Text));
                }
                else
                {
                    MessageBox.Show("parameter lnTe should be a number!");
                    return;
                }

                if (Double.TryParse(txtm.Text, out booleanTemp))
                {
                    parameters.Add(Convert.ToDouble(txtm.Text));
                }
                else
                {
                    MessageBox.Show("parameter m should be a number!");
                    return;
                }

                if (Double.TryParse(txtSr0.Text, out booleanTemp))
                {
                    parameters.Add(Convert.ToDouble(txtSr0.Text));
                }
                else
                {
                    MessageBox.Show("parameter Sr0 should be a number!");
                    return;
                }

                if (Double.TryParse(txtSmax.Text, out booleanTemp))
                {
                    parameters.Add(Convert.ToDouble(txtSmax.Text));
                }
                else
                {
                    MessageBox.Show("parameter Smax should be a number!");
                    return;
                }

                if (Double.TryParse(txtTd.Text, out booleanTemp))
                {
                    parameters.Add(Convert.ToDouble(txtTd.Text));
                }
                else
                {
                    MessageBox.Show("parameter Td should be a number!");
                    return;
                }

                parameters.Add(1000);


                if (Double.TryParse(txtVr.Text, out booleanTemp))
                {
                    parameters.Add(Convert.ToDouble(txtVr.Text));
                }
                else
                {
                    MessageBox.Show("parameter Vr should be a number!");
                    return;
                }

                if (Double.TryParse(txtK0.Text, out booleanTemp))
                {
                    parameters.Add(Convert.ToDouble(txtK0.Text));
                }
                else
                {
                    MessageBox.Show("parameter K0 should be a number!");
                    return;
                }

                if (Double.TryParse(txtCD.Text, out booleanTemp))
                {
                    parameters.Add(Convert.ToDouble(txtCD.Text));
                }
                else
                {
                    MessageBox.Show("parameter CD should be a number!");
                    return;
                }

                parameters.Add(1);

                List<Double> temp = new List<Double>();
                String DEMPath_local = this.DEMPath;

                //Transform the unit of rain from mm to m
                for (int i = 0; i < this.PrecipitationValues.Length; i++)
                {
                    temp.Add(this.PrecipitationValues[i] / 1000);
                }
                Double[] precipitationValues_local = temp.ToArray<Double>();
                temp.Clear();

                //Transform the unit of ET0 from kg/m2 to m
                for (int i = 0; i < this.ET0Values.Length; i++)
                {
                    temp.Add(this.ET0Values[i] / 1000);
                }
                Double[] ET0Values_local = temp.ToArray<Double>();
                temp.Clear();
                Double drainageArea_local = this.drainageArea;
                pTable = RUtility.calculateCustomDischarge(parameters.ToArray<Double>(), DEMPath_local, precipitationValues_local, ET0Values_local, drainageArea_local);

                if (pTable != null)
                {
                    IStandaloneTableCollection pStandaloneCollection = (IStandaloneTableCollection)pMap;
                    IStandaloneTable pAloneTable = new StandaloneTable();
                    pAloneTable.Table = pTable;
                    pAloneTable.Name = "QsimResult" + Convert.ToString(series);
                    pStandaloneCollection.AddStandaloneTable(pAloneTable);
                    pMxDoc.UpdateContents();
                }
                series++;

                DEMPath_local = null;
                precipitationValues_local = null;
                ET0Values_local = null;
                drainageArea_local = 0;
                return;
            }
            else if (rdoCustom.Checked && rdoNash.Checked)
            {
                MessageBox.Show("custom && nse");
                
                List<Double> parameters = new List<double>();
                Double booleanTemp = 0;
                if (Double.TryParse(txtQs0.Text, out booleanTemp))
                {
                    parameters.Add(Convert.ToDouble(txtQs0.Text));
                }
                else
                {
                    MessageBox.Show("parameter Qs0 should be a number!");
                    return;
                }

                if (Double.TryParse(txtlnTe.Text, out booleanTemp))
                {
                    parameters.Add(Convert.ToDouble(txtlnTe.Text));
                }
                else
                {
                    MessageBox.Show("parameter lnTe should be a number!");
                    return;
                }

                if (Double.TryParse(txtm.Text, out booleanTemp))
                {
                    parameters.Add(Convert.ToDouble(txtm.Text));
                }
                else
                {
                    MessageBox.Show("parameter m should be a number!");
                    return;
                }

                if (Double.TryParse(txtSr0.Text, out booleanTemp))
                {
                    parameters.Add(Convert.ToDouble(txtSr0.Text));
                }
                else
                {
                    MessageBox.Show("parameter Sr0 should be a number!");
                    return;
                }

                if (Double.TryParse(txtSmax.Text, out booleanTemp))
                {
                    parameters.Add(Convert.ToDouble(txtSmax.Text));
                }
                else
                {
                    MessageBox.Show("parameter Smax should be a number!");
                    return;
                }

                if (Double.TryParse(txtTd.Text, out booleanTemp))
                {
                    parameters.Add(Convert.ToDouble(txtTd.Text));
                }
                else
                {
                    MessageBox.Show("parameter Td should be a number!");
                    return;
                }

                parameters.Add(1000);


                if (Double.TryParse(txtVr.Text, out booleanTemp))
                {
                    parameters.Add(Convert.ToDouble(txtVr.Text));
                }
                else
                {
                    MessageBox.Show("parameter Vr should be a number!");
                    return;
                }

                if (Double.TryParse(txtK0.Text, out booleanTemp))
                {
                    parameters.Add(Convert.ToDouble(txtK0.Text));
                }
                else
                {
                    MessageBox.Show("parameter K0 should be a number!");
                    return;
                }

                if (Double.TryParse(txtCD.Text, out booleanTemp))
                {
                    parameters.Add(Convert.ToDouble(txtCD.Text));
                }
                else
                {
                    MessageBox.Show("parameter CD should be a number!");
                    return;
                }

                parameters.Add(1);



                List<Double> temp = new List<Double>();
                String DEMPath_local = this.DEMPath;

                //Transform the unit of rain from mm to m
                for (int i = 0; i < this.PrecipitationValues.Length; i++)
                {
                    temp.Add(this.PrecipitationValues[i] / 1000);
                }
                Double[] precipitationValues_local = temp.ToArray<Double>();
                temp.Clear();

                //Transform the unit of discharge from cfs to m/day
                for (int i = 0; i < this.DischargeValues.Length; i++)
                {
                    temp.Add(this.DischargeValues[i] / 35.3147 / this.drainageArea * 86400);
                }
                Double[] DischargeValues_local = temp.ToArray<Double>();
                temp.Clear();

                //Transform the unit of ET0 from kg/m2 to m
                for (int i = 0; i < this.ET0Values.Length; i++)
                {
                    temp.Add(this.ET0Values[i] / 1000);
                }
                Double[] ET0Values_local = temp.ToArray<Double>();
                temp.Clear();

                pTable = RUtility.calculateCustomNSE(parameters.ToArray<Double>(), DEMPath_local, precipitationValues_local, ET0Values_local, DischargeValues_local, this.drainageArea );

                if (pTable != null)
                {
                    IStandaloneTableCollection pStandaloneCollection = (IStandaloneTableCollection)pMap;
                    IStandaloneTable pAloneTable = new StandaloneTable();
                    pAloneTable.Table = pTable;
                    pAloneTable.Name = "Qsim_NSE_Result" + Convert.ToString(series);
                    pStandaloneCollection.AddStandaloneTable(pAloneTable);
                    series++;
                    pMxDoc.UpdateContents();
                }

                DEMPath_local = null;
                precipitationValues_local = null;
                ET0Values_local = null;
                DischargeValues_local = null;
                return;
            }
            else if (rdoMonte.Checked)
            {
                MessageBox.Show("monte");

                
                //List<Double> test = new List<Double>();
                //test.Add(0.00004);
                //test.Add(1);
                //test.Add(0.2);
                //test.Add(0.02);
                //test.Add(2);
                //test.Add(3);
                //test.Add(2500);
                //test.Add(0.01);
                //test.Add(5);
                //test.Add(50);


                List<Double> parameters = new List<double>();
                Double checkTemp = 0;
                if (Double.TryParse(txtQs0.Text, out checkTemp))
                {
                    parameters.Add(Convert.ToDouble(txtQs0.Text));
                }
                else
                {
                    MessageBox.Show("parameter Qs0 should be a number!");
                    return;
                }

                if (Double.TryParse(txtlnTe.Text, out checkTemp))
                {
                    parameters.Add(Convert.ToDouble(txtlnTe.Text));
                }
                else
                {
                    MessageBox.Show("parameter lnTe should be a number!");
                    return;
                }

                if (Double.TryParse(txtm.Text, out checkTemp))
                {
                    parameters.Add(Convert.ToDouble(txtm.Text));
                }
                else
                {
                    MessageBox.Show("parameter m should be a number!");
                    return;
                }

                if (Double.TryParse(txtSr0.Text, out checkTemp))
                {
                    parameters.Add(Convert.ToDouble(txtSr0.Text));
                }
                else
                {
                    MessageBox.Show("parameter Sr0 should be a number!");
                    return;
                }

                if (Double.TryParse(txtSmax.Text, out checkTemp))
                {
                    parameters.Add(Convert.ToDouble(txtSmax.Text));
                }
                else
                {
                    MessageBox.Show("parameter Smax should be a number!");
                    return;
                }

                if (Double.TryParse(txtTd.Text, out checkTemp))
                {
                    parameters.Add(Convert.ToDouble(txtTd.Text));
                }
                else
                {
                    MessageBox.Show("parameter Td should be a number!");
                    return;
                }

                if (Double.TryParse(txtVr.Text, out checkTemp))
                {
                    parameters.Add(Convert.ToDouble(txtVr.Text));
                }
                else
                {
                    MessageBox.Show("parameter Vr should be a number!");
                    return;
                }

                if (Double.TryParse(txtK0.Text, out checkTemp))
                {
                    parameters.Add(Convert.ToDouble(txtK0.Text));
                }
                else
                {
                    MessageBox.Show("parameter K0 should be a number!");
                    return;
                }

                if (Double.TryParse(txtCD.Text, out checkTemp))
                {
                    parameters.Add(Convert.ToDouble(txtCD.Text));
                }
                else
                {
                    MessageBox.Show("parameter CD should be a number!");
                    return;
                }

                if (Double.TryParse(txtTimes.Text, out checkTemp))
                {
                    parameters.Add(Convert.ToDouble(txtTimes.Text));
                }
                else
                {
                    MessageBox.Show("The iteration should be a number!");
                    return;
                }
                List<Double> temp = new List<Double>();
                String DEMPath_local = this.DEMPath;

                //Transform the unit of rain from mm to m
                for (int i = 0; i < this.PrecipitationValues.Length; i++)
                {
                    temp.Add(this.PrecipitationValues[i] / 1000);
                }
                Double[] precipitationValues_local = temp.ToArray<Double>();
                temp.Clear();

                //Transform the unit of discharge from cfs to m/day
                for (int i = 0; i < this.DischargeValues.Length; i++)
                {
                    temp.Add(this.DischargeValues[i] / 35.3147 / this.drainageArea * 86400);
                }
                Double[] DischargeValues_local = temp.ToArray<Double>();
                temp.Clear();

                //Transform the unit of ET0 from kg/m2 to m
                for (int i = 0; i < this.ET0Values.Length; i++)
                {
                    temp.Add(this.ET0Values[i] / 1000);
                }
                Double[] ET0Values_local = temp.ToArray<Double>();
                temp.Clear();

                pTable = RUtility.calculateMonteCarlo(parameters.ToArray<Double>(), DEMPath_local, precipitationValues_local, ET0Values_local, DischargeValues_local);

                if (pTable != null)
                {
                    IStandaloneTableCollection pStandaloneCollection = (IStandaloneTableCollection)pMap;
                    IStandaloneTable pAloneTable = new StandaloneTable();
                    pAloneTable.Table = pTable;
                    pAloneTable.Name = "MonteCarloResult" + Convert.ToString(series);
                    pStandaloneCollection.AddStandaloneTable(pAloneTable);
                    series++;
                    pMxDoc.UpdateContents();
                }

                DEMPath_local = null;
                precipitationValues_local = null;
                ET0Values_local = null;
                DischargeValues_local = null;
                return;
            }
        }

        private void Topmodel_FormClosed(object sender, FormClosedEventArgs e)
        {
            TopmodelAddin.hasInstance = false;
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }














    }
}
